//package inter.utils.pay;
//
//import com.inter.utils.HMACSHA256;
//import com.inter.utils.MD5;
//import com.inter.utils.Md5Encrypt;
//import org.apache.commons.lang.StringUtils;
//import org.apache.http.client.methods.CloseableHttpResponse;
//import org.apache.http.client.methods.HttpPost;
//import org.apache.http.entity.StringEntity;
//import org.apache.http.impl.client.CloseableHttpClient;
//import org.apache.http.impl.client.HttpClients;
//import org.apache.http.util.EntityUtils;
//import org.apache.log4j.Logger;
//
//import javax.servlet.http.HttpServletRequest;
//import java.io.IOException;
//import java.net.InetAddress;
//import java.net.UnknownHostException;
//import java.nio.charset.Charset;
//import java.util.HashMap;
//import java.util.Map;
//import java.util.Random;
//import java.util.regex.Pattern;
//
//public class WxPayUtil {
//    private static Logger logger = Logger.getLogger(WxPayUtil.class);
//
//    /**
//     * 公众号内支付：统一下单
//     *
//     * @param body
//     * @param out_trade_no
//     * @param total_fee
//     * @param IP
//     * @param
//     * @param openid
//     * @return
//     * @throws IOException
//     */
//    public static String unifiedOrder(String body, String out_trade_no, Integer total_fee, String IP, String openid) throws IOException {
//        // 设置访问路径
//        HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
//        // 随机
//        String nonce_str = getNonceStr().toUpperCase();
//        // 组装请求参数,按照ASCII排序
//        String unifiedOrdersign =
//                "appid=" + WxPayConstants.APPID +
//                        "&body=" + body +
//                        "&mch_id=" + WxPayConstants.MCH_ID +
//                        "&nonce_str=" + nonce_str +
//                        "&notify_url=" + WxPayConstants.NOTIFY_URL +
//                        "&openid=" + openid +
//                        "&out_trade_no=" + out_trade_no +
//                        "&spbill_create_ip=" + IP +
//                        "&total_fee=" + total_fee.toString() +
//                        "&trade_type=" + WxPayConstants.TRADE_TYPE_JS +
//                        "&key=" + WxPayConstants.KEY;
//        // 这个字段是用于之后MD5加密的，字段要按照ascii码顺序排序
//        System.out.println("统一下单参与签名的字符串是：" + unifiedOrdersign);
//
//        String sign = MD5.calcMD5(unifiedOrdersign).toUpperCase();
//
//        System.out.println("统一下单参与签名值是：" + sign);
//
//        // 组装包含openid用于请求统一下单返回结果的XML
//        StringBuilder sb = new StringBuilder("");
//        sb.append("<xml>");
//        setXmlKV(sb, "appid", WxPayConstants.APPID);
//        setXmlKV(sb, "body", body);
//        setXmlKV(sb, "mch_id", WxPayConstants.MCH_ID);
//        setXmlKV(sb, "nonce_str", nonce_str);
//        setXmlKV(sb, "notify_url", WxPayConstants.NOTIFY_URL);
//        setXmlKV(sb, "openid", openid);
//        setXmlKV(sb, "out_trade_no", out_trade_no);
//        setXmlKV(sb, "spbill_create_ip", IP);
//        setXmlKV(sb, "total_fee", total_fee.toString());
//        setXmlKV(sb, "trade_type", WxPayConstants.TRADE_TYPE_JS);
//        setXmlKV(sb, "sign", sign);
//        sb.append("</xml>");
//        System.out.println("统一下单请求：" + sb);
//        // 这个处理是为了防止传中文的时候出现签名错误
//        StringEntity reqEntity = new StringEntity(new String(sb.toString().getBytes("UTF-8"), "ISO8859-1"));
//        httppost.setEntity(reqEntity);
//        CloseableHttpClient httpclient = HttpClients.createDefault();
//        CloseableHttpResponse response = httpclient.execute(httppost);
//        String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
//        System.out.println("统一下单返回xml：" + strResult);
//
//        return strResult;
//    }
//
//    /**
//     * 微信H5支付：统一下单
//     *
//     * @param body
//     * @param out_trade_no
//     * @param total_fee
//     * @param IP
//     * @param
//     * @param
//     * @return
//     * @throws IOException
//     */
//    public static String UnifiedOrderH5(String body, String scene_info, String out_trade_no, Integer total_fee, String IP) throws IOException {
//        // 设置访问路径
//        HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
//        // 随机
//        String nonce_str = getNonceStr().toUpperCase();
//        // 组装请求参数,按照ASCII排序
//
//        String unifiedOrdersign =
//                "appid=" + WxPayConstants.APPID +
//                        "&body=" + body +
//                        "&mch_id=" + WxPayConstants.MCH_ID +
//                        "&nonce_str=" + nonce_str +
//                        "&notify_url=" + WxPayConstants.NOTIFY_H5_URL +
//                        "&out_trade_no=" + out_trade_no +
//                        "&scene_info=" + scene_info +
//                        "&spbill_create_ip=" + IP +
//                        "&total_fee=" + total_fee.toString() +
//                        "&trade_type=" + WxPayConstants.TRADE_TYPE_H5 +
//                        "&key=" + WxPayConstants.KEY;
//        // 这个字段是用于之后MD5加密的，字段要按照ascii码顺序排序
//        System.out.println("H5统一下单参与签名的字符串是：" + unifiedOrdersign);
//
//        String sign1 = MD5.calcMD5(unifiedOrdersign).toUpperCase();
//        System.out.println("H5统一下单参与签名值是：" + sign1);
//
//        String sign = Md5Encrypt.md5(unifiedOrdersign).toUpperCase();
//        System.out.println("H5统一下单参与签名值是：" + sign);
//
//        String sign2 = HMACSHA256.sha256_HMAC(unifiedOrdersign, WxPayConstants.KEY).toUpperCase();
//        System.out.println("H5统一下单参与签名值是：" + sign2);
//        // 组装包含openid用于请求统一下单返回结果的XML
//        StringBuilder sb = new StringBuilder("");
//        sb.append("<xml>");
//        setXmlKV(sb, "appid", WxPayConstants.APPID);
//        setXmlKV(sb, "body", body);
//        setXmlKV(sb, "mch_id", WxPayConstants.MCH_ID);
//        setXmlKV(sb, "nonce_str", nonce_str);
//        setXmlKV(sb, "notify_url", WxPayConstants.NOTIFY_H5_URL);
//        setXmlKV(sb, "out_trade_no", out_trade_no);
//        setXmlKV(sb, "scene_info", scene_info);
//        setXmlKV(sb, "spbill_create_ip", IP);
//        setXmlKV(sb, "total_fee", total_fee.toString());
//        setXmlKV(sb, "trade_type", WxPayConstants.TRADE_TYPE_H5);
//        setXmlKV(sb, "sign", sign);
//        sb.append("</xml>");
//        System.out.println("H5统一下单请求：" + sb);
//        // 这个处理是为了防止传中文的时候出现签名错误
//        StringEntity reqEntity = new StringEntity(new String(sb.toString().getBytes("UTF-8"), "ISO8859-1"));
//        httppost.setEntity(reqEntity);
//        CloseableHttpClient httpclient = HttpClients.createDefault();
//        CloseableHttpResponse response = httpclient.execute(httppost);
//        String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
//        System.out.println("H5统一下单返回xml：" + strResult);
//
//        return strResult;
//    }
//
//    /**
//     * 微信APP支付：统一下单
//     *
//     * @param body
//     * @return map
//     * @throws IOException
//     */
//    public static String UnifiedOrderAPP(String body, String orderId, Integer total_fee, String ipAddrStr, String APPID) throws Exception {
//        // 设置访问路径
//        HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
//        // 随机
//        String nonce_str = getNonceStr().toUpperCase();
//        // 组装请求参数,按照ASCII排序
//
//        String unifiedOrdersign =
//                "appid=" + APPID +
//                        "&body=" + body +
//                        "&mch_id=" + WxPayConstants.MCH_ID +
//                        "&nonce_str=" + nonce_str +
//                        "&notify_url=" + WxPayConstants.NOTIFY_APP_URL +
//                        "&out_trade_no=" + orderId +
//                        "&spbill_create_ip=" + ipAddrStr +
//                        "&total_fee=" + total_fee.toString() +
//                        "&trade_type=" + WxPayConstants.TRADE_TYPE_APP +
//                        "&key=" + WxPayConstants.KEY;
//        // 这个字段是用于之后MD5加密的，字段要按照ascii码顺序排序
//        System.out.println("APP统一下单参与签名的字符串是：" + unifiedOrdersign);
//
//        String sign1 = MD5.calcMD5(unifiedOrdersign).toUpperCase();
//        System.out.println("APP统一下单参与签名值是：" + sign1);
//
//        String sign = Md5Encrypt.md5(unifiedOrdersign).toUpperCase();
//        System.out.println("APP统一下单参与签名值是：" + sign);
//
//        String sign2 = HMACSHA256.sha256_HMAC(unifiedOrdersign, WxPayConstants.KEY).toUpperCase();
//        System.out.println("APP统一下单参与签名值是：" + sign2);
//        // 组装包含openid用于请求统一下单返回结果的XML
//        StringBuilder sb = new StringBuilder("");
//        sb.append("<xml>");
//        setXmlKV(sb, "appid", APPID);
//        setXmlKV(sb, "body", body);
//        setXmlKV(sb, "mch_id", WxPayConstants.MCH_ID);
//        setXmlKV(sb, "nonce_str", nonce_str);
//        setXmlKV(sb, "notify_url", WxPayConstants.NOTIFY_APP_URL);
//        setXmlKV(sb, "out_trade_no", orderId);
//        setXmlKV(sb, "spbill_create_ip", ipAddrStr);
//        setXmlKV(sb, "total_fee", total_fee.toString());
//        setXmlKV(sb, "trade_type", WxPayConstants.TRADE_TYPE_APP);
//        setXmlKV(sb, "sign", sign);
//        sb.append("</xml>");
//        System.out.println("APP统一下单请求：" + sb);
//        // 这个处理是为了防止传中文的时候出现签名错误
//        StringEntity reqEntity = new StringEntity(new String(sb.toString().getBytes("UTF-8"), "ISO8859-1"));
//        httppost.setEntity(reqEntity);
//        CloseableHttpClient httpclient = HttpClients.createDefault();
//        CloseableHttpResponse response = httpclient.execute(httppost);
//        String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
//        System.out.println("APP统一下单返回xml：" + strResult);
//
//        return strResult;
//    }
//
//    /*****
//     * 微信扫二维码支付
//     * @param body
//     * @param orderId
//     * @param totel_fee
//     * @param ipAddrStr
//     * @return
//     */
//    public static String UnifiedOrderScan(String body, String orderId, Integer totel_fee, String ipAddrStr) throws Exception {
//        // 设置访问路径
//        HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
//        // 随机
//        String nonce_str = getNonceStr().toUpperCase();
//        // 组装请求参数,按照ASCII排序
//
//        String unifiedOrdersign =
//                "appid=" + WxPayConstants.APPID +
//                        "&body=" + body +
//                        "&mch_id=" + WxPayConstants.MCH_ID +
//                        "&nonce_str=" + nonce_str +
//                        "&notify_url=" + WxPayConstants.NOTIFY_APP_URL +
//                        "&out_trade_no=" + orderId +
//                        "&spbill_create_ip=" + ipAddrStr +
//                        "&total_fee=" + totel_fee.toString() +
//                        "&trade_type=" + WxPayConstants.TRADE_TYPE_SCAN +
//                        "&key=" + WxPayConstants.KEY;
//        // 这个字段是用于之后MD5加密的，字段要按照ascii码顺序排序
//        System.out.println("扫二维码支付统一下单参与签名的字符串是：" + unifiedOrdersign);
//
//        String sign1 = MD5.calcMD5(unifiedOrdersign).toUpperCase();
//        System.out.println("扫二维码支付统一下单参与签名值是：" + sign1);
//
//        String sign = Md5Encrypt.md5(unifiedOrdersign).toUpperCase();
//        System.out.println("扫二维码支付统一下单参与签名值是：" + sign);
//
//        String sign2 = HMACSHA256.sha256_HMAC(unifiedOrdersign, WxPayConstants.KEY).toUpperCase();
//        System.out.println("扫二维码支付统一下单参与签名值是：" + sign2);
//        // 组装包含openid用于请求统一下单返回结果的XML
//        StringBuilder sb = new StringBuilder("");
//        sb.append("<xml>");
//        setXmlKV(sb, "appid", WxPayConstants.APPID);
//        setXmlKV(sb, "body", body);
//        setXmlKV(sb, "mch_id", WxPayConstants.MCH_ID);
//        setXmlKV(sb, "nonce_str", nonce_str);
//        setXmlKV(sb, "notify_url", WxPayConstants.NOTIFY_APP_URL);
//        setXmlKV(sb, "out_trade_no", orderId);
//        setXmlKV(sb, "spbill_create_ip", ipAddrStr);
//        setXmlKV(sb, "total_fee", totel_fee.toString());
//        setXmlKV(sb, "trade_type", WxPayConstants.TRADE_TYPE_SCAN);
//        setXmlKV(sb, "sign", sign);
//        sb.append("</xml>");
//        System.out.println("扫二维码支付统一下单请求：" + sb);
//        // 这个处理是为了防止传中文的时候出现签名错误
//        StringEntity reqEntity = new StringEntity(new String(sb.toString().getBytes("UTF-8"), "ISO8859-1"));
//        httppost.setEntity(reqEntity);
//        CloseableHttpClient httpclient = HttpClients.createDefault();
//        CloseableHttpResponse response = httpclient.execute(httppost);
//        String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
//        System.out.println("扫二维码支付统一下单返回xml：" + strResult);
//
//        return strResult;
//    }
//
//    /***
//     * 获取扫码支付预下单后，微信回复的prepay_id和trade_type和code_url
//     * @param prePayInfoXml
//     * @return
//     */
//    public static Map<String, Object> getPayScanMap(String prePayInfoXml) {
//        Map<String, Object> map = new HashMap<String, Object>();
//        String result_code = getXmlPara(prePayInfoXml, "result_code");
//        String return_code = getXmlPara(prePayInfoXml, "return_code");
//        String return_msg = getXmlPara(prePayInfoXml, "return_msg");
//        System.out.println("result_code是：" + result_code + ";return_code是：" + return_code + ";return_msg是：" + return_msg);
//
//        if ("SUCCESS".equals(result_code) && "SUCCESS".equals(return_code)) {
//            // 统一下单返回xml中prepay_id （预支付交易会话标识）
//            String prepay_id = getXmlPara(prePayInfoXml, "prepay_id");
//            String trade_type = getXmlPara(prePayInfoXml, "trade_type");
//            String code_url=getXmlPara(prePayInfoXml, "code_url");
//            System.out.println("返回的prepay_id是：" + prepay_id + ";返回的trade_type是：" + trade_type+";返回的code_url是："+code_url);
//            map.put("prepay_id", prepay_id);
//            map.put("trade_type", trade_type);
//            map.put("code_url",code_url);
//            map.put("result_code", result_code);
//            map.put("return_code", return_code);
//            map.put("return_msg", return_msg);
//            System.out.println("扫二维码支付统一下单返回map：" + map);
//            return map;
//        } else {
//            map.put("result_code", result_code);
//            map.put("return_code", return_code);
//            map.put("return_msg", return_msg);
//            System.out.println("扫二维码支付统一下单未取到预下单号：" + map);
//            return map;
//        }
//    }
//
//    /**
//     * 获取微信公众号支付下单返回的参数
//     * 根据统一下单返回预支付订单的id和其他信息生成签名并拼装为map（调用微信支付）
//     *
//     * @param prePayInfoXml
//     * @return
//     */
//    public static Map<String, Object> getPayMap(String prePayInfoXml) {
//        Map<String, Object> map = new HashMap<String, Object>();
//        String prepay_id = getXmlPara(prePayInfoXml, "prepay_id");// 统一下单返回xml中prepay_id
//        String timeStamp = String.valueOf((System.currentTimeMillis() / 1000));// 1970年到现在的秒数
//        String nonceStr = getNonceStr().toUpperCase();// 随机数据字符串
//        String packageStr = "prepay_id=" + prepay_id;
//        String signType = "MD5";
//
//        String paySign1 =
//                "appId=" + WxPayConstants.APPID +
//                        "&nonceStr=" + nonceStr +
//                        "&package=" + packageStr +
//                        //"&prepay_id="+prepay_id+
//                        "&signType=" + signType +
//                        "&timeStamp=" + timeStamp +
//                        "&key=" + WxPayConstants.KEY;
//        // 注意这里的参数要根据ASCII码排序
//        System.out.println("getPayMap参与签名的字符串是：" + paySign1);
//        String paySign = MD5.calcMD5(paySign1).toUpperCase();
//        // 将数据MD5加密
//        map.put("appId", WxPayConstants.APPID);
//        map.put("timeStamp", timeStamp);
//        map.put("nonceStr", nonceStr);
//        map.put("packageStr", packageStr);
//        map.put("signType", signType);
//        map.put("paySign", paySign);
//        map.put("prepay_id", prepay_id);
//        System.out.println("统一下单返回map：" + map);
//        return map;
//    }
//
//    /**
//     * 获取h5支付下单返回的参数
//     * 根据统一下单返回预支付订单的id和其他信息生成签名并拼装为map（调用微信支付）
//     *
//     * @param
//     * @return
//     */
//    public static Map<String, Object> getPayH5Map(String prePayInfoXml) {
//        Map<String, Object> map = new HashMap<String, Object>();
//        String result_code = getXmlPara(prePayInfoXml, "result_code");
//        String return_code = getXmlPara(prePayInfoXml, "return_code");
//        System.out.println("result_code是：" + result_code + ";return_code是：" + return_code);
//
//        if ("SUCCESS".equals(result_code) && "SUCCESS".equals(return_code)) {
//            // 统一下单返回xml中prepay_id （预支付交易会话标识）
//            String prepay_id = getXmlPara(prePayInfoXml, "prepay_id");
//
//            String mweb_url = getXmlPara(prePayInfoXml, "mweb_url");
//            // 统一下单返回xml中mweb_url （支付跳转链接）,支付成功跳转redirect_url的链接
//            //String mweb_url = getXmlPara(prePayInfoXml, "mweb_url") + "&redirect_url=" + URLEncoder.encode(WxPayConstants.paySuccess);
//            System.out.println("返回的mweb_url应该是：" + mweb_url);
//            map.put("prepay_id", prepay_id);
//            map.put("mweb_url", mweb_url);
//            System.out.println("H5统一下单返回map：" + map);
//            return map;
//        }
//        return null;
//    }
//
//    /**
//     * 获取APP支付下单返回的参数
//     * 根据统一下单返回预支付订单的id和其他信息生成签名并拼装为map（调用微信支付）
//     *
//     * @param
//     * @return
//     */
//    public static Map<String, Object> getPayAPPMap(String prePayInfoXml) {
//        Map<String, Object> map = new HashMap<String, Object>();
//        String result_code = getXmlPara(prePayInfoXml, "result_code");
//        String return_code = getXmlPara(prePayInfoXml, "return_code");
//        String return_msg = getXmlPara(prePayInfoXml, "return_msg");
//        System.out.println("result_code是：" + result_code + ";return_code是：" + return_code + ";return_msg是：" + return_msg);
//
//        if ("SUCCESS".equals(result_code) && "SUCCESS".equals(return_code)) {
//            // 统一下单返回xml中prepay_id （预支付交易会话标识）
//            String prepay_id = getXmlPara(prePayInfoXml, "prepay_id");
//            String trade_type = getXmlPara(prePayInfoXml, "trade_type");
//            System.out.println("返回的prepay_id是：" + prepay_id + ";返回的trade_type是：" + trade_type);
//            map.put("prepay_id", prepay_id);
//            map.put("trade_type", trade_type);
//            map.put("result_code", result_code);
//            map.put("return_code", return_code);
//            map.put("return_msg", return_msg);
//            System.out.println("APP统一下单返回map：" + map);
//            return map;
//        } else {
//            map.put("result_code", result_code);
//            map.put("return_code", return_code);
//            map.put("return_msg", return_msg);
//            System.out.println("APP统一下单未取到预下单号：" + map);
//            return map;
//        }
//
//    }
//
//    /**
//     * 修改订单状态，获取微信回调结果
//     *
//     * @param request
//     * @return 应该是流只能用一次的问题
//     */
//    public static Map getNotifyResult(HttpServletRequest request) {
//        String inputLine;
//        String notifyXml = "";
//        String resXml = "";
//        try {
//            while ((inputLine = request.getReader().readLine()) != null) {
//                notifyXml += inputLine;
//            }
//            request.getReader().close();
//        } catch (Exception e) {
//            logger.debug("xml获取失败：" + e);
//            e.printStackTrace();
//        }
//        System.out.println("接收到的xml：" + notifyXml);
//        logger.debug("收到微信异步回调：");
//        logger.debug(notifyXml);
//
//        String appid = getXmlPara(notifyXml, "appid");
//        String bank_type = getXmlPara(notifyXml, "bank_type");
//        String cash_fee = getXmlPara(notifyXml, "cash_fee");
//        String fee_type = getXmlPara(notifyXml, "fee_type");
//        String is_subscribe = getXmlPara(notifyXml, "is_subscribe");
//        String mch_id = getXmlPara(notifyXml, "mch_id");
//        String nonce_str = getXmlPara(notifyXml, "nonce_str");
//        String openid = getXmlPara(notifyXml, "openid");
//        String out_trade_no = getXmlPara(notifyXml, "out_trade_no");
//        String result_code = getXmlPara(notifyXml, "result_code");
//        String return_code = getXmlPara(notifyXml, "return_code");
//        String sign = getXmlPara(notifyXml, "sign");
//        String time_end = getXmlPara(notifyXml, "time_end");
//        String total_fee = getXmlPara(notifyXml, "total_fee");
//        String trade_type = getXmlPara(notifyXml, "trade_type");
//        String transaction_id = getXmlPara(notifyXml, "transaction_id");
//
//        // 根据返回xml计算本地签名
//        String localSign =
//                "appid=" + appid +
//                        "&bank_type=" + bank_type +
//                        "&cash_fee=" + cash_fee +
//                        "&fee_type=" + fee_type +
//                        "&is_subscribe=" + is_subscribe +
//                        "&mch_id=" + mch_id +
//                        "&nonce_str=" + nonce_str +
//                        "&openid=" + openid +
//                        "&out_trade_no=" + out_trade_no +
//                        "&result_code=" + result_code +
//                        "&return_code=" + return_code +
//                        "&time_end=" + time_end +
//                        "&total_fee=" + total_fee +
//                        "&trade_type=" + trade_type +
//                        "&transaction_id=" + transaction_id +
//                        "&key=" + WxPayConstants.KEY;
//        // 注意这里的参数要根据ASCII码 排序
//        //将数据MD5加密
//        String localSign1 = MD5.calcMD5(localSign).toUpperCase();
//        System.out.println("localSign1本地签名是：" + localSign1);
//
//        localSign = Md5Encrypt.md5(localSign).toUpperCase();
//        System.out.println("localSign本地签名是：" + localSign);
//
//        logger.debug("微信签名是：" + sign);
//        System.out.println("本地签名是：" + sign);
//
//        if ("SUCCESS".equalsIgnoreCase(result_code) && "SUCCESS".equalsIgnoreCase(return_code)) {
//            //成功
//            System.out.println("支付成功");
//            logger.debug("公众号支付成功，out_trade_no(订单号)为：" + out_trade_no);
//            logger.debug("公众号支付成功，total_fee(金额)为：" + total_fee);
//            logger.debug("公众号支付成功，result_code(回调返回)为：" + result_code);
//            logger.debug("公众号支付成功，return_code(用户返回)为：" + return_code);
//            resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
//
//        } else {
//            System.out.println("返回错误结果码");
//            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[FAIL]]></return_msg>" + "</xml> ";
//        }
//
//        //---------------------------------------------------------------------------
//        //返回一个map，map中包含了回复给微信的xml和调用北京接口的参数
//        Map<String, Object> returnMap = new HashMap<String, Object>();
//        returnMap.put("resXml", resXml);
//        returnMap.put("out_trade_no", out_trade_no);
//        returnMap.put("total_fee", total_fee);
//        returnMap.put("result_code", result_code);
//        returnMap.put("return_code", return_code);
//
//        returnMap.put("appid", appid);
//        returnMap.put("bank_type", bank_type);
//        returnMap.put("cash_fee", cash_fee);
//        returnMap.put("fee_type", fee_type);
//
//        returnMap.put("is_subscribe", is_subscribe);
//        returnMap.put("mch_id", mch_id);
//        returnMap.put("nonce_str", nonce_str);
//        returnMap.put("openid", openid);
//
//        returnMap.put("sign", sign);
//        returnMap.put("time_end", time_end);
//        returnMap.put("trade_type", trade_type);
//        returnMap.put("transaction_id", transaction_id);
//
//        //---------------------------------------------------------------------------
//        return returnMap;
//    }
//
//    /**
//     * 修改订单状态，获取微信回调结果
//     *
//     * @param request
//     * @return 应该是流只能用一次的问题
//     */
//    public static Map getH5NotifyResult(HttpServletRequest request) {
//        String inputLine;
//        String notifyXml = "";
//        String resXml = "";
//        try {
//            while ((inputLine = request.getReader().readLine()) != null) {
//                notifyXml += inputLine;
//            }
//            request.getReader().close();
//        } catch (Exception e) {
//            logger.debug("xml获取失败：" + e);
//            e.printStackTrace();
//        }
//        System.out.println("接收到的xml：" + notifyXml);
//        logger.debug("收到微信异步回调：");
//        logger.debug(notifyXml);
//
//        String appid = getXmlPara(notifyXml, "appid");
//        String bank_type = getXmlPara(notifyXml, "bank_type");
//        String cash_fee = getXmlPara(notifyXml, "cash_fee");
//        String fee_type = getXmlPara(notifyXml, "fee_type");
//        String is_subscribe = getXmlPara(notifyXml, "is_subscribe");
//        String mch_id = getXmlPara(notifyXml, "mch_id");
//        String nonce_str = getXmlPara(notifyXml, "nonce_str");
//        String openid = getXmlPara(notifyXml, "openid");
//        String out_trade_no = getXmlPara(notifyXml, "out_trade_no");
//        String result_code = getXmlPara(notifyXml, "result_code");
//        String return_code = getXmlPara(notifyXml, "return_code");
//        String sign = getXmlPara(notifyXml, "sign");
//        String time_end = getXmlPara(notifyXml, "time_end");
//        String total_fee = getXmlPara(notifyXml, "total_fee");
//        String trade_type = getXmlPara(notifyXml, "trade_type");
//        String transaction_id = getXmlPara(notifyXml, "transaction_id");
//
//        // 根据返回xml计算本地签名
//        String localSign =
//                "appid=" + appid +
//                        "&bank_type=" + bank_type +
//                        "&cash_fee=" + cash_fee +
//                        "&fee_type=" + fee_type +
//                        "&is_subscribe=" + is_subscribe +
//                        "&mch_id=" + mch_id +
//                        "&nonce_str=" + nonce_str +
//                        "&openid=" + openid +
//                        "&out_trade_no=" + out_trade_no +
//                        "&result_code=" + result_code +
//                        "&return_code=" + return_code +
//                        "&time_end=" + time_end +
//                        "&total_fee=" + total_fee +
//                        "&trade_type=" + trade_type +
//                        "&transaction_id=" + transaction_id +
//                        "&key=" + WxPayConstants.KEY;
//        // 注意这里的参数要根据ASCII码 排序
//        //将数据MD5加密
//        localSign = MD5.calcMD5(localSign).toUpperCase();
//        System.out.println("返回xml原来的签名：" + localSign);
//        //localSign =Md5Encrypt.md5(localSign).toUpperCase();
//        //System.out.println("返回xml新的签名："+localSign);
//
//        // 本地计算签名与微信返回签名不同||返回结果为不成功
//        if (!sign.equals(localSign) || "FAIL".equals(result_code) || "FAIL".equals(return_code)) {
//            System.out.println("验证签名失败或支付失败！");
//            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[FAIL]]></return_msg>" + "</xml> ";
//        } else {
//            resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
//            System.out.println("支付成功，out_trade_no(订单号)为：" + out_trade_no + ";total_fee(金额)为:" + total_fee + ";result_code(回调返回)为:" + result_code);
//        }
//        //---------------------------------------------------------------------------
//        //返回一个map，map中包含了回复给微信的xml和调用北京接口的参数
//        Map<String, Object> returnMap = new HashMap<String, Object>();
//        returnMap.put("resXml", resXml);
//        returnMap.put("out_trade_no", out_trade_no);
//        returnMap.put("total_fee", total_fee);
//        returnMap.put("result_code", result_code);
//        returnMap.put("return_code", return_code);
//        returnMap.put("appid", appid);
//        returnMap.put("bank_type", bank_type);
//        returnMap.put("cash_fee", cash_fee);
//        returnMap.put("fee_type", fee_type);
//        returnMap.put("is_subscribe", is_subscribe);
//        returnMap.put("mch_id", mch_id);
//        returnMap.put("nonce_str", nonce_str);
//        returnMap.put("openid", openid);
//        returnMap.put("sign", sign);
//        returnMap.put("time_end", time_end);
//        returnMap.put("trade_type", trade_type);
//        returnMap.put("transaction_id", transaction_id);
//
//        //---------------------------------------------------------------------------
//        return returnMap;
//    }
//
//    /****
//     * 获取微信支付结果回调的方法
//     * @param request
//     * @return
//     */
//    public static Map getAppNotifyResult(HttpServletRequest request) {
//        String inputLine;
//        String notifyXml = "";
//        String resXml = "";
//        try {
//            while ((inputLine = request.getReader().readLine()) != null) {
//                notifyXml += inputLine;
//            }
//            request.getReader().close();
//        } catch (Exception e) {
//            logger.debug("APP-xml获取失败：" + e);
//            e.printStackTrace();
//        }
//        System.out.println("APP-接收到的xml：" + notifyXml);
//        logger.debug("APP-收到微信异步回调：");
//        logger.debug(notifyXml);
//
//        String appid = getXmlPara(notifyXml, "appid");
//        String bank_type = getXmlPara(notifyXml, "bank_type");
//        String cash_fee = getXmlPara(notifyXml, "cash_fee");
//        String fee_type = getXmlPara(notifyXml, "fee_type");
//        String is_subscribe = getXmlPara(notifyXml, "is_subscribe");
//        String mch_id = getXmlPara(notifyXml, "mch_id");
//        String nonce_str = getXmlPara(notifyXml, "nonce_str");
//        String openid = getXmlPara(notifyXml, "openid");
//        String out_trade_no = getXmlPara(notifyXml, "out_trade_no");
//        String result_code = getXmlPara(notifyXml, "result_code");
//        String return_code = getXmlPara(notifyXml, "return_code");
//        String sign = getXmlPara(notifyXml, "sign");
//        String time_end = getXmlPara(notifyXml, "time_end");
//        String total_fee = getXmlPara(notifyXml, "total_fee");
//        String trade_type = getXmlPara(notifyXml, "trade_type");
//        String transaction_id = getXmlPara(notifyXml, "transaction_id");
//
//        // 根据返回xml计算本地签名
//        String localSign =
//                "appid=" + appid +
//                        "&bank_type=" + bank_type +
//                        "&cash_fee=" + cash_fee +
//                        "&fee_type=" + fee_type +
//                        "&is_subscribe=" + is_subscribe +
//                        "&mch_id=" + mch_id +
//                        "&nonce_str=" + nonce_str +
//                        "&openid=" + openid +
//                        "&out_trade_no=" + out_trade_no +
//                        "&result_code=" + result_code +
//                        "&return_code=" + return_code +
//                        "&time_end=" + time_end +
//                        "&total_fee=" + total_fee +
//                        "&trade_type=" + trade_type +
//                        "&transaction_id=" + transaction_id +
//                        "&key=" + WxPayConstants.KEY;
//        // 注意这里的参数要根据ASCII码 排序
//        //将数据MD5加密
//        localSign = MD5.calcMD5(localSign).toUpperCase();
//        System.out.println("返回xml原来的签名：" + localSign);
//
//        // 本地计算签名与微信返回签名不同||返回结果为不成功
//        if (!sign.equals(localSign) || "FAIL".equals(result_code) || "FAIL".equals(return_code)) {
//            System.out.println("APP-验证签名失败或支付失败！");
//            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[FAIL]]></return_msg>" + "</xml> ";
//        } else {
//            resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
//            System.out.println("APP-支付成功，out_trade_no(订单号)为：" + out_trade_no + ";total_fee(金额)为:" + total_fee + ";result_code(回调返回)为:" + result_code);
//        }
//        //---------------------------------------------------------------------------
//        //返回一个map，map中包含了回复给微信的xml和调用北京接口的参数
//        Map<String, Object> returnMap = new HashMap<String, Object>();
//        returnMap.put("resXml", resXml);
//        returnMap.put("out_trade_no", out_trade_no);
//        returnMap.put("total_fee", total_fee);
//        returnMap.put("result_code", result_code);
//        returnMap.put("return_code", return_code);
//        returnMap.put("appid", appid);
//        returnMap.put("bank_type", bank_type);
//        returnMap.put("cash_fee", cash_fee);
//        returnMap.put("fee_type", fee_type);
//        returnMap.put("is_subscribe", is_subscribe);
//        returnMap.put("mch_id", mch_id);
//        returnMap.put("nonce_str", nonce_str);
//        returnMap.put("openid", openid);
//        returnMap.put("sign", sign);
//        returnMap.put("time_end", time_end);
//        returnMap.put("trade_type", trade_type);
//        returnMap.put("transaction_id", transaction_id);
//
//        //---------------------------------------------------------------------------
//        return returnMap;
//    }
//
//    /**
//     * 获取32位随机字符串
//     *
//     * @return
//     */
//    public static String getNonceStr() {
//        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
//        StringBuilder sb = new StringBuilder();
//        Random rd = new Random();
//        for (int i = 0; i < 32; i++) {
//            sb.append(str.charAt(rd.nextInt(str.length())));
//        }
//        return sb.toString();
//    }
//
//    /**
//     * 插入XML标签
//     *
//     * @param sb
//     * @param Key
//     * @param value
//     * @return
//     */
//    public static StringBuilder setXmlKV(StringBuilder sb, String Key,
//                                         String value) {
//        sb.append("<");
//        sb.append(Key);
//        sb.append(">");
//
//        sb.append(value);
//
//        sb.append("</");
//        sb.append(Key);
//        sb.append(">");
//
//        return sb;
//    }
//
//    /**
//     * 解析XML 获得名称为para的参数值
//     *
//     * @param xml
//     * @param para
//     * @return
//     */
//    public static String getXmlPara(String xml, String para) {
//        int start = xml.indexOf("<" + para + ">");
//        int end = xml.indexOf("</" + para + ">");
//
//        if (start < 0 && end < 0) {
//            return null;
//        }
//        return xml.substring(start + ("<" + para + ">").length(), end)
//                .replace("<![CDATA[", "").replace("]]>", "");
//    }
//
//    /**
//     * 获取ip地址
//     *
//     * @param request
//     * @return
//     */
//    public static String getIpAddr(HttpServletRequest request) {
//        InetAddress addr = null;
//        try {
//            addr = InetAddress.getLocalHost();
//        } catch (UnknownHostException e) {
//            return request.getRemoteAddr();
//        }
//        byte[] ipAddr = addr.getAddress();
//        String ipAddrStr = "";
//        for (int i = 0; i < ipAddr.length; i++) {
//            if (i > 0) {
//                ipAddrStr += ".";
//            }
//            ipAddrStr += ipAddr[i] & 0xFF;
//        }
//        return ipAddrStr;
//    }
//
//    /*****
//     * 去查询订单的方法
//     * @param transaction_id
//     * @param out_trade_no
//     * @return
//     */
//    public static String orderQuery(String transaction_id, String out_trade_no) {
//        try {
//            // 设置访问路径
//            HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/pay/orderquery");
//
//            String nonce_str = getNonceStr().toUpperCase();// 随机
//
//            //以上两个参数只用选其中一个就行了，侧重用transaction_id，比较准确，但是是异步的怕无法及时
//            if (!out_trade_no.equals("")) {
//                if (!transaction_id.equals("")) {
//                    //两个参数都不为空，就用transaction_id去查询
//                    // 组装请求参数,按照ASCII排序
//                    String orderQuerysign =
//                            "appid=" + WxPayConstants.APPID +
//                                    "&mch_id=" + WxPayConstants.MCH_ID +
//                                    "&nonce_str=" + nonce_str +
//                                    "&transaction_id=" + transaction_id +
//                                    "&key=" + WxPayConstants.KEY;// 这个字段是用于之后MD5加密的，字段要按照ascii码顺序排序
//                    System.out.println("订单查询参与签名的字符串是：" + orderQuerysign);
//                    //StringUtil.convertCharset(unifiedOrdersign, "UTF-8", "ISO-8859-1")
//                    String sign = MD5.calcMD5(orderQuerysign).toUpperCase();
//
//                    System.out.println("订单查询参与签名值是：" + sign);
//                    // sign = Md5Encrypt.md5(sign).toUpperCase();
//                    // 组装包含openid用于请求统一下单返回结果的XML
//                    StringBuilder sb = new StringBuilder("");
//                    sb.append("<xml>");
//                    setXmlKV(sb, "appid", WxPayConstants.APPID);
//                    setXmlKV(sb, "mch_id", WxPayConstants.MCH_ID);
//                    setXmlKV(sb, "nonce_str", nonce_str);
//                    setXmlKV(sb, "transaction_id", transaction_id);
//                    setXmlKV(sb, "sign", sign);
//                    sb.append("</xml>");
//                    System.out.println("订单查询请求：" + sb);
//                    StringEntity reqEntity = new StringEntity(new String(sb.toString().getBytes("UTF-8"), "ISO8859-1"));// 这个处理是为了防止传中文的时候出现签名错误
//                    httppost.setEntity(reqEntity);
//                    CloseableHttpClient httpclient = HttpClients.createDefault();
//                    CloseableHttpResponse response = httpclient.execute(httppost);
//                    String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
//                    System.out.println("订单查询返回xml：" + strResult);
//
//                    return strResult;
//                }
//                // 只有out_trade_no 不为空时，用out_trade_no去查询
//                // 组装请求参数,按照ASCII排序
//                String orderQuerysign =
//                        "appid=" + WxPayConstants.APPID +
//                                "&mch_id=" + WxPayConstants.MCH_ID +
//                                "&nonce_str=" + nonce_str +
//                                "&out_trade_no=" + out_trade_no +
//                                "&key=" + WxPayConstants.KEY;// 这个字段是用于之后MD5加密的，字段要按照ascii码顺序排序
//                System.out.println("订单查询参与签名的字符串是：" + orderQuerysign);
//                //StringUtil.convertCharset(unifiedOrdersign, "UTF-8", "ISO-8859-1")
//                String sign = MD5.calcMD5(orderQuerysign).toUpperCase();
//
//                System.out.println("订单查询参与签名值是：" + sign);
//                // sign = Md5Encrypt.md5(sign).toUpperCase();
//                // 组装包含openid用于请求统一下单返回结果的XML
//                StringBuilder sb = new StringBuilder("");
//                sb.append("<xml>");
//                setXmlKV(sb, "appid", WxPayConstants.APPID);
//                setXmlKV(sb, "mch_id", WxPayConstants.MCH_ID);
//                setXmlKV(sb, "nonce_str", nonce_str);
//                setXmlKV(sb, "out_trade_no", out_trade_no);
//                setXmlKV(sb, "sign", sign);
//                sb.append("</xml>");
//                System.out.println("订单查询请求：" + sb);
//                // 这个处理是为了防止传中文的时候出现签名错误
//                StringEntity reqEntity = new StringEntity(new String(sb.toString().getBytes("UTF-8"), "ISO8859-1"));
//                httppost.setEntity(reqEntity);
//                CloseableHttpClient httpclient = HttpClients.createDefault();
//                CloseableHttpResponse response = httpclient.execute(httppost);
//                String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
//                System.out.println("订单查询返回xml：" + strResult);
//
//                return strResult;
//            }
//
//        } catch (Exception e) {
//
//            e.printStackTrace();
//        }
//        return null;
//    }
//
//    /*****
//     * 获取去查询订单微信的首次回复
//     * @param request
//     * @return
//     */
//
//    public static Map getH5OrderQueryNotifyResult(HttpServletRequest request) {
//        String inputLine;
//        String notifyXml = "";
//        try {
//            while ((inputLine = request.getReader().readLine()) != null) {
//                notifyXml += inputLine;
//            }
//            request.getReader().close();
//        } catch (Exception e) {
//            logger.debug("xml获取失败：" + e);
//            e.printStackTrace();
//        }
//        System.out.println("查询订单接收到的xml：" + notifyXml);
//        logger.debug(notifyXml);
//
//        String return_code = getXmlPara(notifyXml, "return_code");
//        String return_msg = getXmlPara(notifyXml, "return_msg");
//        String appid = getXmlPara(notifyXml, "appid");
//        String mch_id = getXmlPara(notifyXml, "mch_id");
//        String device_info = getXmlPara(notifyXml, "device_info");
//        String nonce_str = getXmlPara(notifyXml, "nonce_str");
//        String sign = getXmlPara(notifyXml, "sign");
//        String result_code = getXmlPara(notifyXml, "result_code");
//        String openid = getXmlPara(notifyXml, "openid");
//        String is_subscribe = getXmlPara(notifyXml, "is_subscribe");
//        String trade_type = getXmlPara(notifyXml, "trade_type");
//        String out_trade_no = getXmlPara(notifyXml, "out_trade_no");
//        String bank_type = getXmlPara(notifyXml, "bank_type");
//        String total_fee = getXmlPara(notifyXml, "total_fee");
//        String fee_type = getXmlPara(notifyXml, "fee_type");
//        String transaction_id = getXmlPara(notifyXml, "transaction_id");
//        String attach = getXmlPara(notifyXml, "attach");
//        String time_end = getXmlPara(notifyXml, "time_end");
//        String trade_state = getXmlPara(notifyXml, "trade_state");
//
//        // 根据返回xml计算本地签名
//        String localSign =
//                "appid=" + appid +
//                        "&attach=" + attach +
//                        "&bank_type=" + bank_type +
//                        "&device_info=" + device_info +
//                        "&fee_type=" + fee_type +
//                        "&is_subscribe=" + is_subscribe +
//                        "&mch_id=" + mch_id +
//                        "&nonce_str=" + nonce_str +
//                        "&openid=" + openid +
//                        "&out_trade_no=" + out_trade_no +
//                        "&result_code=" + result_code +
//                        "&return_code=" + return_code +
//                        "&return_msg=" + return_msg +
//                        "&time_end=" + time_end +
//                        "&total_fee=" + total_fee +
//                        "&trade_state=" + trade_state +
//                        "&trade_type=" + trade_type +
//                        "&transaction_id=" + transaction_id +
//                        "&key=" + WxPayConstants.KEY;// 注意这里的参数要根据ASCII码 排序
//
//        localSign = MD5.calcMD5(localSign).toUpperCase();//将数据MD5加密
//        //localSign = HMACSHA256.sha256_HMAC(localSign, WxPayConstants.KEY).toUpperCase();
//        logger.debug("查询接口本地签名是：" + localSign);
//        logger.debug("查询微信支付签名是：" + sign);
//        // 本地计算签名与微信返回签名不同||返回结果为不成功
//        if (!sign.equals(localSign)) {
//            //签名未通过
//            System.out.println("验证签名失败或返回错误结果码");
//        } else {
//            //查询成功！返回结果给前端
//            Map<String, Object> returnMap = new HashMap<String, Object>();
//            returnMap.put("out_trade_no", out_trade_no);
//            returnMap.put("transaction_id", transaction_id);
//            returnMap.put("trade_state", trade_state);
//            return returnMap;
//        }
//
//        return null;
//    }
//
//    /*
//     * 方法二：推荐，速度最快 判断是否为整数
//     *
//     * @param str 传入的字符串
//     *
//     * @return 是整数返回true,否则返回false
//     * Pattern.compile("^[-\\+]?[\\d]*$")不要在方法体内直接实现
//     */
//    private static Pattern NUMBER_PATTERN = Pattern.compile("^[-\\+]?[\\d]*$");
//
//    public static boolean isInteger(String str) {
//        Pattern pattern = NUMBER_PATTERN;
//        return pattern.matcher(str).matches();
//    }
//
//    /***
//     * 用于获取用户真实ip的方法
//     * @param request
//     * @return
//     */
//    public static String getIp2(HttpServletRequest request) {
//        String ip = request.getHeader("X-Forwarded-For");
//        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
//            //多次反向代理后会有多个ip值，第一个ip才是真实ip
//            int index = ip.indexOf(",");
//            if (index != -1) {
//                return ip.substring(0, index);
//            } else {
//                return ip;
//            }
//        }
//        ip = request.getHeader("X-Real-IP");
//        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
//            return ip;
//        }
//        return request.getRemoteAddr();
//    }
//
//
//}
